import Info from 'components/Markdown/Info'

export const meta = {
  title: 'Overview',
  position: 100,
}

## What are Prisma bindings?

Prisma bindings are _GraphQL bindings_ for the GraphQL APIs exposed by Prisma services.

<Info>

This page introduces the idea of Prisma bindings and explains how they can be used to build GraphQL servers. To learn more about the API of Prisma bindings, visit the documentation for GraphQL bindings [here](https://oss.prisma.io/content/GraphQL-Binding/01-Overview.html).


To learn more about the differences between Prisma bindings and the [Prisma client](/prisma-client), you can read [this](https://www.prisma.io/forum/t/help-understanding-prisma-clients-value-proposition/4394/17) forum post.

</Info>

### The idea of GraphQL bindings

GraphQL bindings are minimal, auto-generated and schema-specific GraphQL clients. A GraphQL binding lets you talk to a GraphQL API by invoking auto-generated binding functions rather than manually constructing and sending HTTP requests.

Consider the following GraphQL schema definition as an example:

```graphql
type User {
  id: ID!
  name: String!
}

type Query {
  users: [User!]!
}

type Mutation {
  createUser(name: String!): User!
}
```

The API defined by this schema accepts two operations, the `users` query and the `createUser` mutation.

Consequently, a GraphQL binding for this API exposes exactly two functions named after the _root fields_ of the schema:

- `binding.query.users(args, selectionSet)` is generated based on the `users` root field
- `binding.mutation.createUser(args, selectionSet)` is generated based on the `createUser` root field

Both functions are auto-generated and when invoked, they construct and send the respective query/mutation to the API. 

### Bindings functions construct and send operations to a GraphQL API

But how does the binding know _what fields to include in the selection set_ of the query it constructs and sends to the API? 

Same question for the `name` argument of the `createUser` mutation, how does the auto-generated binding function know _what parameter values to provide_ when constructing the actual mutation?

That's exactly what the two arguments of the generated binding functions are for:

- `args` is an object carrying any _parameters_ for the operation.
- `selectionSet` is a string specifying the _selection set_ of the operation, i.e. what fields should be included in the returned JSON response (this can also be provided as an object).

Let's now understand how the `users` binding function can be used to construct and send the following query to the GraphQL API:

```graphql
query {
  users {
    id
    name
  }
}
```

To achieve this, you need to invoke the `users` function as follows:

```js
binding.query.users({}, `{ id name }`)
```

The first argument passed to `users` is an empty object (because the `users` root field in the schema definition above doesn't accept any parameters). 

The second argument is the selection set - to achieve the same result as the sample query above, we need to include `id` and the `name`.

The selection set passed as the second argument actually is a _GraphQL fragment_ (in this case on the `User` type). Binding functions however accept a shorthand notation that omits the `fragment` keyword as well the fragment name. So instead of:

```graphql
fragment UserFragment on User {
  id
  name
}
```

you can simply write: 

```
{ id name }
````

New lines are generally ignored in GraphQL.

Let's now go through the same exercise for `createUser` and think about how we can send the following mutation using one of the binding functions:

```graphql
mutation {
  createUser(name: "Sarah") {
    id
  }
}
```

This mutation can be sent using the `createUser` binding function:

```js
binding.mutation.createUser({ name: "Sarah" }, `{ id }`)
```

This time, we're providing an object that contains the values for the parameters of the mutation as the first argument. In this case, there's only the `name` to be provided. 

Similar to the `users` query, we're also passing the selection set (written again as a shorthand GraphQL fragment) as the second argument. Because the selection set in the sample mutation above only includes the `id`, that's what we're doing in the function call as well.

### GraphQL bindings: An auto-generated SDK for your GraphQL API

Another way of looking at GraphQL bindings is as _auto-generated SDKs for GraphQL APIs_. An SDK is a library that exposes a set of _convenience_ functions for you to interact with a (web) API. Instead of talking to the API _directly_, you can use the utilities provided by the SDK which reduces boilerplate and (ideally) improves the developer ergonomics of communicating with the API.

GraphQL bindings effectively serve the same purpose. The binding functions are equivalent to the root fields of the corresponding GraphQL schema and allow to interact with the GraphQL API in a more convenient way.

![](https://i.imgur.com/meI1A4S.png)

### Prisma bindings have additional Prisma-specific features

Prisma bindings are a _superset_ of GraphQL bindings, they're an extended version of GraphQL bindings specifically for Prisma APIs.

There are two extra features in Prisma bindings (compared to regular GraphQL bindings):

- baked in authentication using the _service secret_
- the `exists` function lets you to check whether a certain element exists in the database

> Prisma bindings use the [data loader](https://github.com/facebook/dataloader) pattern to batch requests to the Prisma API.

### Baked in authentication

The _service secret_ is passed to the constructor of the `Prisma` binding. This allows the binding to generate the required _service token_ (JWT) when it sends requests to your service's API.

Consider the following example:

```js
const Prisma = require('prisma-binding')

const prisma = new Prisma({
  typeDefs: 'prisma.graphql',
  endpoint: 'http://localhost:4466/myservice/dev',
  secret: 'mysecret42',
})
```

The `prisma` binding object can now be used to send requests directly to your service by invoking the auto-generated binding functions. Each request will be authenticated with a _service token_ generated based on the `secret` that was passed to the `Prisma` constructor.

### Checking for existence with `exists`

As mentioned, the `exists` function allows to easily check whether a certain element exists in the database. You can provide filter criteria to the function call and it will return a boolean value indicating whether (at least) one element meeting those criteria exists. As an example, say a Prisma service was based on the following data model:

```graphql
type Post {
  id: ID! @unique
  title: String!
}
```

For each type in your data model, the `Prisma` binding creates a dedicated `exists` function that is named after the type. Here are a few examples demonstrating how `exists` can be used:

```js
// Check whether a `Post` with a specific `id` exists
prisma.exists.Post({ id: "cji4iv4ucwc1c0a9671z7t8pt" })

// Check whether a `Post` exists whose `id` is in the provided list
prisma.exists.Post({ id_in: ["cji4iv4ucwc1c0a9671z7t8pt", "cji4k3j9w29yq0a96xp5fufj1", "cji4j2g0lxis40a9604a80kmx"] })

// Check whether a `Post` exists that has `I like GraphQL` as `title`
prisma.exists.Post({ title: "I like GraphQL" })

// Check whether a `Post` exists where the `title`contains the string `GraphQL`
prisma.exists.Post({ title_contains: "GraphQL" })`
```

### Schema delegation using the `info` object

Prisma bindings can be used in two _modes_:

- Provide the selection set as a _string_ (similar to all examples you've seen on this page)
- Provide the selection set as the `info` object _inside a resolver function_

The second mode is referred to as _schema delegation_. Schema delegation only works when there is an `info` object available and therefore the _only context where schema delegation is possible is inside of resolver functions_.

> The `info` object is the _fourth_ argument passed into a resolver function. It carries the AST and other useful information about the query that's currently being resolved, e.g. what parameter values were provided. Learn more about it [here](https://www.prisma.io/blog/graphql-server-basics-demystifying-the-info-argument-in-graphql-resolvers-6f26249f613a/).

The idea of schema delegation is that a GraphQL query that's received by GraphQL server **`A`** is not resolved by **`A`**'s execution engine. Instead, **`A`** _delegates_ the query to GraphQL server **`B`** whose GraphQL execution engine will finally take care of resolving the query.

![](https://i.imgur.com/csz6Ck8.png)

In this example, the `feed` resolver in the application server _delegates_ the resolution of the incoming query to the `posts` resolver of the Prisma API. Note that this only works when the respective fields of both resolvers have the same _type_.

The `info` object passed into the `feed` resolver carries the AST of the initial `feed` query. This AST contains information about the query's selection set, in this case it contains the `id` and `title` fields. The binding function extracts this information from the `info` object and therefore is able to construct a corresponding query which it sends to Prisma.

## Building GraphQL servers with Prisma bindings

### Database layer vs Application layer

Before discussing how to implement your resolvers using Prisma bindings and schema delegation, let's understand the general architecture of your GraphQL server.

The most important part to understand is that when building GraphQL servers with Prisma, you're dealing with two(!) GraphQL APIs:

- The **database layer** is provided by Prisma's CRUD/realtime GraphQL API. The GraphQL schema defining this API is the auto-generated **Prisma GraphQL schema**.
- The **application layer** is responsible for any functionality that's _not directly_ related to writing or reading data from the database (like business logic, authentication and permissions, 3rd-party integrations,...). When working with Node.JS, the application layer is commonly implemented with the [`graphql-yoga`](https://github.com/graphcool/graphql-yoga) library. The GraphQL schema defining the API of the application layer is called **application schema**.

![](https://i.imgur.com/CIXK9kg.png)

The application layer is where you'll spend most of your actual _coding_ work. Here you need to _define the GraphQL schema_ for the API your client applications will talk to and _implement the corresponding resolver functions_ (these resolvers will be delegating requests to Prisma).

The layered architectural approach is best practice in modern application development, separating business logic from database access. It is similar to architectures used by companies like [Twitter](https://about.sourcegraph.com/graphql/graphql-at-twitter/) or [Facebook](https://www.facebook.com/notes/facebook-engineering/tao-the-power-of-the-graph/10151525983993920/) where a dedicated data access layer abstracts away the underlying database and provides a _data access API_ consumed by the application layer. 

The core benefit of this layered architectural approach is a clear _separation of concerns_. Removing the complexity of database access and putting it into its own layer lets application developers focus on implementing business logic and value-adding features. The database layer takes care of various concerns related to database access, such as _security_, _synchronization_, _query optimization_ and other _performance_-related tasks.

### Bridging application and database layer: An example

When building a GraphQL server with Prisma, these are the high-level steps you need to perform:

1. **Configure database layer**
    1. Specify your _data model_ for your Prisma service in SDL
    1. _Deploy_ a Prisma service based on that data model
1. **Implement application layer**
    1. Write the _application schema_ (i.e. define the operations of your API)
    1. Implement _resolver functions_ for the API operations (using Prisma bindings)
    1. Configure and _start the GraphQL server_ with application schema and resolvers

Let's get concrete and walk through an example. 

#### 1.1. Specify data model for Prisma service

The first step is to define the data model for a Prisma service, here is the one for this example:

```graphql
type Post {
  id: ID! @unique
  title: String!
  content: String!
  published: Boolean! @default(value: "false")
}
```

#### 1.2. Deploy a Prisma service

To deploy the Prisma service, we also need a minimal prisma.yml. Assumed the above data model is stored in a file called `datamodel.graphql`, this is what prisma.yml could look like:

```yml
endpoint: http://localhost:4466
datatamodel: datamodel.graphql
```

Now you can run `prisma deploy` and the service will be deployed to a Prisma server running on `http://localhost:4466`.

The Prisma GraphQL schema for the generated Prisma API looks similar to this (this is a shortened version, find the full version [here](https://gist.github.com/nikolasburk/88f08d6e8d863dbe5c67ec92cec7011e)):

```graphql
type Post implements Node {
  id: ID!
  title: String!
  content: String!
  published: Boolean!
}

type Mutation {
  createPost(data: PostCreateInput!): Post!
  updatePost(data: PostUpdateInput!, where: PostWhereUniqueInput!): Post
  deletePost(where: PostWhereUniqueInput!): Post
}

type Query {
  posts(where: PostWhereInput, orderBy: PostOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [Post]!
  post(where: PostWhereUniqueInput!): Post
}

type Subscription {
  post(where: PostSubscriptionWhereInput): PostSubscriptionPayload
}
```

The API defined by this schema can now be accessed on `http://localhost:4466`.

#### 2.1. Write application schema

> In the following it is assumed that the Prisma GraphQL schema is available to the application layer as a file called `prisma.graphql` (it might have been downloaded via a _post-deployment hook_).

To write the application schema, you need to think about the API operations that should be exposed to your clients. This is your chance to transform Prisma's generic CRUD operations into a domain-specific API suited to your clients' needs.

For example, if you wanted to build a blogging app, the following GraphQL schema would already encode some _domain rules_ specific to your app:

```graphql
# import Post from "prisma.graphql" 

type Query {
  feed: [Post!]!
  findPostById(id: ID!): Post
}

type Mutation {
  createDraft(title: String!, content: String!): Post!
  publish(id: ID!): Post
  deletePost(id: ID!): Post
}
```

The main point of creating this application schema is to narrow down the scope of possible actions for your clients. Instead of getting full CRUD access, clients are only able to perform operations following your business rules.

Here's a quick run-through of the available operations (note that `Post` elements where `published` is `false` are called _drafts_): 

- `feed`: Returns all _published_ posts
- `findPostById`: Returns any post by its id
- `createDraft`: Create a new _draft_
- `publish`: Publish a _draft_ (it will then be returned by `feed`)
- `deletePost`: Delete any post by its id

#### 2.2. Implement resolver functions

Each of the five root fields in the above application schema needs to have a corresponding resolver function. Here is what the implementation of these resolvers is going to look like:

```js
const resolvers = {
  Query: {
    feed: (parent, args, context, info) => {
      return context.db.query.posts({ where: { published: true } }, info)
    },
    findPostById: (parent, args, context, info) => {
      return context.db.query.post({ where: { id: args.id } }, info)
    },
  },
  Mutation: {
    createDraft: (parent, args, context, info) => {
      return context.db.mutation.createPost(
        {
          data: {
            title: args.title,
            published: false,
          },
        },
        info,
      )
    },
    publish: (parent, args, context, info) => {
      return context.db.mutation.updatePost(
        {
          where: { id: args.id },
          data: { published: true },
        },
        info,
      )
    },
    deletePost: (parent, args, context, info) => {
      return context.db.mutation.deletePost({ where: { id: args.id } }, info)
    },
  },
}
```

All resolver follow a similar pattern in that it uses the Prisma binding object (called `db`) that's attached to the `context`. The binding object exposes the operations of the Prisma API. 

All a resolver needs to do is invoke the correct binding function and pass on the `info` object. The application layer will never talk to the database directly but only through the Prisma API.

#### 2.3. Configure and start the GraphQL server

```js
const { GraphQLServer } = require('graphql-yoga')
const { Prisma } = require('prisma-binding')
const resolvers = require('./resolvers')

const server = new GraphQLServer({
  typeDefs: './schema.graphql'
  resolvers,
  context: {
    db: new Prisma({
      typeDefs: './prisma.graphql',
      endpoint: 'http://localhost:4466'
    })
  }
})
server.start(() => console.log(`Server is running on http://localhost:4000`))
```

In this configuration, we assume that the schema definition from **2.1.** and the resolver implementation from **2.2.** are available in files called `schema.graphql` and `resolvers.js`. They're both passed to the constructor of the `GraphQLServer`. 

The `Prisma` binding instance is further attached to the `context` of the `GraphQLServer`. This is the reason why the resolvers are able to invoke Prisma binding functions, because they get access to the binding object through the `context` object.

> If you want to explore this particular example, check out the corresponding step-by-step tutorial.

## Lifecycle of a GraphQL query

The goal for this section is to understand the end-to-end flow for sending a GraphQL query to your application server and receiving the response, including its path through Prisma.

### **Step 1: The client sends a GraphQL query to the application server**

The `findPostById` query from the application schema is used as an example. Assume a client sends the following query to your application server:

```graphql
query {
  findPostById(id: "cji4iv4ucwc1c0a9671z7t8pt") {
    id
    title
    published
  }
} 
```

### Step 2: The application server receives the GraphQL query

A GraphQL server resolves a query by invoking the resolver functions for the fields contained in the query. The first field in the incoming query is `findPostById`, so the `findPostById` resolver is the first one to be invoked. As a reminder, this is what the `findPostById` resolver looks like:

```js
findPostById: (parent, args, context, info) => {
  return context.db.query.post({ where: { id: args.id } }, info)
},
```

### Step 3: The Prisma binding to constructs a query for the Prisma API

The `findPostById` resolver only has one line of code: `return context.db.query.post({ where: { id: args.id } }, info)`.

Invoking the `post` binding function means that a `post` query will be constructed:

```graphql
query {
  post(???) {
    ???
  }
}
```

To know which parameters the binding function injects into the query, we need to look at the first argument passed into the binding function. In this case it is an object looking as follows: `{ where: { id: args.id } }`. The value of `args.id` is `cji4iv4ucwc1c0a9671z7t8pt`. Consequently, the binding functions injects the following query arguments:

```graphql
query {
  post(where: {
    id: "cji4iv4ucwc1c0a9671z7t8pt"
  }) {
    ???
  }
}
```

Finally, the binding function needs to know the _selection set_ for the query. That's the purpose of the second argument passed into it. The `info` object contains the AST of the initial `feed` query. The binding function now extracts the selection set from that query and injects it into the query for the Prisma API:

```graphql
query {
  post(where: {
    id: "cji4iv4ucwc1c0a9671z7t8pt"
  }) {
    id
    title
    published
  }
}
```

### Step 4: The binding function sends the constructed query to the Prisma API

The `post` query is now sent to the Prisma service where it's being resolved. Prisma generates a corresponding database query and retrieves the requested data from the database.

### Step 5: The Prisma API returns the requested data

Assume the Prisma API responds with the following data:

```json
{
  "data": {
    "post": {
      "id": "cji4iv4ucwc1c0a9671z7t8pt",
      "title": "GraphQL is cool",
      "published": true
    }
  }
}
```

### Step 6: The binding function receives the response from the Prisma API

The `post` binding function receives the payload of the service's response. It strips off the `"data"` key from the JSON object and returns the following `post` object:

```json
{
  "post": {
    "id": "cji4iv4ucwc1c0a9671z7t8pt",
    "title": "GraphQL is cool",
    "published": true
  }
}
```

### Step 7: The `post` object is returned by the `findPostById` resolver

The `findPostById` resolver is next in the server's callstack. It returns the `post` object that just came out of the `post` binding function, again including the `id`, `title` and `published` properties.

### Step 8: The application server returns the response

Before the HTTP response is returned, the GraphQL execution engine wraps the `post` object (that was returned by the `findPostbyId` resolver)  with the `"data"` key ([this is required by the GraphQL specification](http://facebook.github.io/graphql/draft/#sec-Data)):

```json
{
  "data": {
    "post": {
      "id": "cji4iv4ucwc1c0a9671z7t8pt",
      "title": "GraphQL is cool",
      "published": true
    }
  }
}
```
